// =============================================
// 该代码段通常位于一个 HLSL 文件（比如 FractalGPU.hlsl）中，
// 用于支持 GPU Instancing（实例化渲染）时，
// 从 Unity 传递过来的每实例变换矩阵（float3x4）中读取数据，
// 并设置到 Unity 内置的 unity_ObjectToWorld 矩阵中，
// 从而让每个实例在渲染时拥有自己独立的位置、旋转和缩放。
// =============================================

// ----------------------------------------------------------------
// 条件编译：仅在启用了 Unity 的「程序化实例化（Procedural Instancing）」时编译下面的代码
// UNITY_PROCEDURAL_INSTANCING_ENABLED 是 Unity 在启用 GPU Instancing 时自动定义的宏
// ----------------------------------------------------------------
#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)

    // 声明一个 StructuredBuffer（结构化缓冲区），用于接收从 CPU（C#/Job）传递过来的矩阵数据
    // 每个元素是一个 float3x4 类型的矩阵，代表一个实例的「物体空间 -> 世界空间」的变换（位置+旋转+缩放）
    // 该缓冲区在 C# 端通常通过 ComputeBuffer 传入，并在 Shader 中通过 _Matrices 名称访问
    StructuredBuffer<float3x4> _Matrices;

#endif 

// ----------------------------------------------------------------
// 函数：ConfigureProcedural()
// 作用：这是一个由 Unity 调用的特殊函数，用于在「程序化实例化（Procedural Instancing）」模式下，
//       为当前正在绘制的实例设置其「物体到世界空间」的变换矩阵（unity_ObjectToWorld）。
//       该函数会在 GPU Instancing 的顶点着色器执行之前被调用。
// ----------------------------------------------------------------
void ConfigureProcedural () {

    #if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)

        // 从 _Matrices 缓冲区中，根据当前实例的 ID（unity_InstanceID）取出对应的变换矩阵
        // unity_InstanceID 是 Unity 自动提供的，表示当前正在处理的实例的索引（从 0 开始）
        float3x4 m = _Matrices[unity_InstanceID];

        // ----------------------------------------------------------------
        // 将取出的 float3x4 矩阵 m 的各个部分，赋值给 Unity 内置的 unity_ObjectToWorld 矩阵的对应部分
        // unity_ObjectToWorld 是一个 float4x4 矩阵，表示从物体的本地坐标系 -> 世界坐标系的变换
        // 但我们传入的是 float3x4，它只有前 3 行（旋转+缩放），第 4 行（平移）需要单独处理
        // ----------------------------------------------------------------

        // 设置 unity_ObjectToWorld 的第 0 行（即 X 轴相关变换：旋转+缩放）
        unity_ObjectToWorld._m00_m01_m02_m03 = m._m00_m01_m02_m03;

        // 设置 unity_ObjectToWorld 的第 1 行（即 Y 轴相关变换）
        unity_ObjectToWorld._m10_m11_m12_m13 = m._m10_m11_m12_m13;

        // 设置 unity_ObjectToWorld 的第 2 行（即 Z 轴相关变换）
        unity_ObjectToWorld._m20_m21_m22_m23 = m._m20_m21_m22_m23;

        unity_ObjectToWorld._m30_m31_m32_m33 = float4(0.0, 0.0, 0.0, 1.0);

    #endif  // UNITY_PROCEDURAL_INSTANCING_ENABLED
}


// ----------------------------------------------------------------
// 以下两个函数：ShaderGraphFunction_float 和 ShaderGraphFunction_half
// 看起来像是用于 Shader Graph（Unity 的可视化着色器编辑工具）的兼容性函数，
// 它们只是简单地将输入的 float3 / half3 向量原样输出，
// 是为了在 Shader Graph 中调用某个自定义节点时作为桥梁函数使用。
// ----------------------------------------------------------------

// 一个空实现的函数，输入 float3，输出 float3，原样返回
void ShaderGraphFunction_float (float3 In, out float3 Out) {
    Out = In;
}

// 一个空实现的函数，输入 half3，输出 half3，原样返回
void ShaderGraphFunction_half (half3 In, out half3 Out) {
    Out = In;
}